import request from 'supertest';
import app from '../src/app';
import { createTestDatabase, cleanupTestDatabase } from './utils/database';
import { PrismaClient } from '@prisma/client';

describe('AppController (e2e)', () => {
  let prisma: PrismaClient;

  beforeAll(async () => {
    const { prisma: testPrisma } = await createTestDatabase();
    prisma = testPrisma;
  });

  afterAll(async () => {
    await cleanupTestDatabase();
  });

  describe('Health Check', () => {
    it('/ (GET)', () => {
      return request(app)
        .get('/')
        .expect(200)
        .expect('Content-Type', /json/)
        .expect((res) => {
          expect(res.body).toEqual({
            status: 'ok',
            timestamp: expect.any(String),
            version: expect.any(String),
          });
        });
    });
  });

  describe('Authentication', () => {
    it('/api/auth/login (POST) - should validate required fields', () => {
      return request(app)
        .post('/api/auth/login')
        .send({})
        .expect(400)
        .expect((res) => {
          expect(res.body).toHaveProperty('error');
          expect(res.body.error).toContain('required');
        });
    });

    it('/api/auth/login (POST) - should reject invalid credentials', () => {
      return request(app)
        .post('/api/auth/login')
        .send({
          email: 'invalid@example.com',
          password: 'wrongpassword',
        })
        .expect(401)
        .expect((res) => {
          expect(res.body).toHaveProperty('error');
          expect(res.body.error).toContain('Invalid credentials');
        });
    });
  });

  describe('Audit Logs', () => {
    let authToken: string;

    beforeAll(async () => {
      // Create test user
      const testUser = {
        email: 'test@example.com',
        password: 'hashedpassword',
        name: 'Test User',
        role: 'ADMIN',
      };

      await prisma.$executeRaw`
        INSERT INTO "User" (email, password, name, role)
        VALUES (${testUser.email}, ${testUser.password}, ${testUser.name}, ${testUser.role})
      `;

      const loginResponse = await request(app)
        .post('/api/auth/login')
        .send({
          email: testUser.email,
          password: 'password123',
        });

      authToken = loginResponse.body.token;
    });

    afterAll(async () => {
      await prisma.$executeRaw`DELETE FROM "User" WHERE email = 'test@example.com'`;
    });

    it('/api/audit-logs (GET) - should require authentication', () => {
      return request(app)
        .get('/api/audit-logs')
        .expect(401);
    });

    it('/api/audit-logs (GET) - should list audit logs', () => {
      return request(app)
        .get('/api/audit-logs')
        .set('Authorization', `Bearer ${authToken}`)
        .expect(200)
        .expect((res) => {
          expect(Array.isArray(res.body.logs)).toBeTruthy();
          expect(res.body).toHaveProperty('total');
          expect(res.body).toHaveProperty('page');
          expect(res.body).toHaveProperty('limit');
        });
    });

    it('/api/audit-logs (POST) - should create audit log', () => {
      return request(app)
        .post('/api/audit-logs')
        .set('Authorization', `Bearer ${authToken}`)
        .send({
          action: 'CREATE',
          entityType: 'USER',
          entityId: '123',
          details: { key: 'value' },
        })
        .expect(201)
        .expect((res) => {
          expect(res.body).toHaveProperty('id');
          expect(res.body.action).toBe('CREATE');
          expect(res.body.entityType).toBe('USER');
        });
    });
  });
});
